package net.cyl.aspect;

import com.alibaba.cloud.commons.lang.StringUtils;
import lombok.extern.slf4j.Slf4j;
import net.cyl.annotation.RepeatSubmit;
import net.cyl.constant.RedisKey;
import net.cyl.emums.BizCodeEnum;
import net.cyl.exception.BizException;
import net.cyl.interceptor.LoginInterceptor;
import net.cyl.util.CommonUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

@Aspect
@Component
@Slf4j
public class RepeatSubmitAspect {
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private RedissonClient redissonClient;
    @Pointcut("@annotation(repeatSubmit)")
    public void pointCutNoRepeatSubmit(RepeatSubmit repeatSubmit) {

    }
    @Around("pointCutNoRepeatSubmit(repeatSubmit)")
    public Object around(ProceedingJoinPoint joinPoint, RepeatSubmit repeatSubmit) throws Throwable {

        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        boolean res = false;
        long accountNo = LoginInterceptor.loginUserThreadLocal.get().getAccountNo();
        String type =repeatSubmit.limitType().name();
        if(type.equalsIgnoreCase((RepeatSubmit.Type.PARAM.name()))){
            // TODO
          long lockTime=repeatSubmit.lockTime();
          String ipAddr= CommonUtil.getIpAddr(request);
          MethodSignature signature = (MethodSignature) joinPoint.getSignature();
          Method method = signature.getMethod();
          String className=method.getDeclaringClass().getName();
          String key="order-server:repeat_submit:"+CommonUtil.MD5(String.format("%s-%s-%s-%s",ipAddr,accountNo,className,method.getName()));
          //加锁TODO
//            res= Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(key, "1", lockTime, TimeUnit.SECONDS));
            RLock lock = redissonClient.getLock(key);
            res = lock.tryLock(0,lockTime, TimeUnit.SECONDS);

        }
        else{
            // TODO
            String requestToken=request.getHeader("request-token");
            if(StringUtils.isEmpty(requestToken)){
                throw new BizException(BizCodeEnum.ORDER_CONFIRM_TOKEN_EQUAL_FAIL);
            }
            String key = String.format(RedisKey.SUBMIT_ORDER_TOKEN_KEY,accountNo,requestToken);
       
            res = redisTemplate.delete(key);
        }
        if(!res){
            log.info("重复提交");
            return null;
        }
        log.info("环绕通知执行前");
        Object proceed = joinPoint.proceed();
        log.info("环绕通知执行后");
        return proceed;
    }
}
